#encoding=utf-8
#py2.7
import os
from struct import pack
from pdb import set_trace as int3
import zlib
'''
#鬼哭街
DecTable=[
    0x21, 0xE1, 0xA0, 0x8D, 0x86, 0xF1, 0xE3, 0xE9, 0x00, 0xB6, 0x2D, 0xD7, 0x6A, 0x43, 0x93, 0xB0, 0xEC, 0x0A, 0xCF, 0x37, 0xB8, 0x3E, 0x9E, 0xF9, 0x9A, 0x4D, 0xC8, 0x7D, 0x5A, 0x77, 0x3A, 0x3D,
    0x12, 0x27, 0x17, 0xCA, 0x89, 0x8F, 0x6C, 0x9C, 0x5F, 0x0F, 0x40, 0x64, 0xCD, 0x20, 0x3F, 0xFD, 0xB9, 0x73, 0xBE, 0x30, 0xEB, 0xAD, 0xB3, 0x10, 0xEE, 0x38, 0x7A, 0xFA, 0xD5, 0x4B, 0x5D, 0xB5,
    0xE6, 0x91, 0xA5, 0xE7, 0xDA, 0xAA, 0x75, 0x0D, 0x3C, 0x9F, 0xF8, 0x7E, 0xB2, 0xA4, 0x62, 0xAB, 0xCB, 0x03, 0x6E, 0x18, 0xE5, 0x46, 0xC1, 0x4E, 0xFF, 0x63, 0x01, 0x97, 0xE2, 0x1A, 0x76, 0x65,
    0x49, 0xCC, 0x1C, 0xBB, 0x09, 0x54, 0x58, 0xC9, 0x87, 0x05, 0xF2, 0x14, 0x52, 0xDC, 0x23, 0xF0, 0xDF, 0x7F, 0xED, 0x04, 0xAC, 0x16, 0xA8, 0x0E, 0x1F, 0xAE, 0xBA, 0x66, 0x6F, 0x5E, 0xD2, 0x96,
    0xFE, 0x61, 0x69, 0xB7, 0x55, 0xA7, 0x45, 0x1D, 0xB1, 0x80, 0x2A, 0xC4, 0x70, 0x6D, 0xF5, 0x9D, 0xD4, 0xDE, 0x79, 0x74, 0x07, 0xC2, 0x2B, 0xA9, 0xBC, 0x25, 0x13, 0x5B, 0x15, 0x22, 0x06, 0x8C,
    0x82, 0xF3, 0x29, 0x94, 0xA1, 0xA6, 0x7B, 0x9B, 0xD8, 0xA3, 0x98, 0x1E, 0x11, 0x1B, 0x35, 0x59, 0x02, 0xFB, 0x99, 0xD6, 0xB4, 0x72, 0xD3, 0x4C, 0x90, 0xC0, 0xBF, 0x2C, 0xEF, 0x8B, 0x88, 0xFC,
    0x53, 0x51, 0x85, 0xD1, 0xDB, 0x56, 0x4A, 0xF4, 0x19, 0x92, 0x33, 0x42, 0xC3, 0x36, 0x26, 0x60, 0x2E, 0xD0, 0xAF, 0x83, 0xF7, 0x48, 0x78, 0x4F, 0x95, 0x08, 0xC6, 0x32, 0xCE, 0x3B, 0x34, 0xD9,
    0x57, 0x5C, 0xDD, 0xE8, 0x31, 0xC7, 0x7C, 0xE4, 0x67, 0x71, 0x50, 0x0B, 0x81, 0x44, 0x0C, 0xC5, 0x24, 0x8A, 0x41, 0x8E, 0xE0, 0x39, 0x2F, 0xA2, 0x68, 0x6B, 0xEA, 0xF6, 0x84, 0xBD, 0x28, 0x47,
]'''

'''#Axanael
DecTable=[
	0x21, 0x71, 0xF0, 0xD8, 0xD6, 0x81, 0x73, 0x7C, 0x00, 0x46, 0x28, 0x67, 0xBD, 0x93, 0xE3, 0x40, 0x7F, 0x0D, 0x5A, 0x37, 0x4B, 0x39, 0xE9, 0x8C, 0xED, 0x98, 0x5B, 0xC8, 0xAD, 0xC7, 0x3D, 0x38,
	0x12, 0x27, 0x17, 0x5D, 0xDC, 0xDA, 0xBF, 0xEF, 0xAA, 0x0A, 0x90, 0xB4, 0x58, 0x20, 0x3A, 0x88, 0x4C, 0xC3, 0x49, 0x30, 0x7E, 0xF8, 0x43, 0x10, 0x79, 0x3B, 0xCD, 0x8D, 0x65, 0x9E, 0xA8, 0x45,
	0x76, 0xE1, 0xF5, 0x77, 0x6D, 0xFD, 0xC5, 0x08, 0x3F, 0xEA, 0x8B, 0xC9, 0x42, 0xF4, 0xB2, 0xFE, 0x5E, 0x03, 0xB9, 0x1B, 0x75, 0x96, 0x51, 0x99, 0x8A, 0xB3, 0x01, 0xE7, 0x72, 0x1D, 0xC6, 0xB5,
	0x9C, 0x5F, 0x1F, 0x4E, 0x0C, 0xA4, 0xAB, 0x5C, 0xD7, 0x05, 0x82, 0x14, 0xA2, 0x6F, 0x23, 0x80, 0x6A, 0xCA, 0x78, 0x04, 0xFF, 0x16, 0xFB, 0x09, 0x1A, 0xF9, 0x4D, 0xB6, 0xBA, 0xA9, 0x62, 0xE6,
	0x89, 0xB1, 0xBC, 0x47, 0xA5, 0xF7, 0x95, 0x18, 0x41, 0xD0, 0x2D, 0x54, 0xC0, 0xB8, 0x85, 0xE8, 0x64, 0x69, 0xCC, 0xC4, 0x07, 0x52, 0x2E, 0xFC, 0x4F, 0x25, 0x13, 0xAE, 0x15, 0x22, 0x06, 0xDF,
	0xD2, 0x83, 0x2C, 0xE4, 0xF1, 0xF6, 0xCE, 0xEE, 0x6B, 0xF3, 0xEB, 0x19, 0x11, 0x1E, 0x35, 0xAC, 0x02, 0x8E, 0xEC, 0x66, 0x44, 0xC2, 0x63, 0x9F, 0xE0, 0x50, 0x4A, 0x2F, 0x7A, 0xDE, 0xDB, 0x8F,
	0xA3, 0xA1, 0xD5, 0x61, 0x6E, 0xA6, 0x9D, 0x84, 0x1C, 0xE2, 0x33, 0x92, 0x53, 0x36, 0x26, 0xB0, 0x29, 0x60, 0xFA, 0xD3, 0x87, 0x9B, 0xCB, 0x9A, 0xE5, 0x0B, 0x56, 0x32, 0x59, 0x3E, 0x34, 0x6C,
	0xA7, 0xAF, 0x68, 0x7B, 0x31, 0x57, 0xCF, 0x74, 0xB7, 0xC1, 0xA0, 0x0E, 0xD1, 0x94, 0x0F, 0x55, 0x24, 0xDD, 0x91, 0xD9, 0x70, 0x3C, 0x2A, 0xF2, 0xBB, 0xBE, 0x7D, 0x86, 0xD4, 0x48, 0x2B, 0x97,
]'''

#君と彼女と彼女の恋
DecTable=[
0x57, 0xD7, 0x66, 0x10, 0x14, 0xE7, 0xDF, 0xD8, 0x36, 0x74, 0x50, 0x95, 0xC9, 0xAF, 0x2F, 0x76, 0xDD, 0x39, 0x82, 0xF5, 0x7A, 0xF1, 0x21, 0xE8, 0x29, 0xA0, 0x8A, 0x00, 0xB9, 0x05, 0xF9, 0xF0,
0x4B, 0x55, 0x45, 0x89, 0x18, 0x12, 0xCD, 0x2D, 0xB2, 0x32, 0xA6, 0xC3, 0x80, 0x56, 0xF2, 0xE0, 0x78, 0x0F, 0x71, 0xF6, 0xDC, 0x60, 0x7F, 0x46, 0xD1, 0xFA, 0x09, 0xE9, 0x9E, 0xAC, 0xB0, 0x7E,
0xD4, 0x27, 0x6E, 0xD5, 0x99, 0x69, 0x0E, 0x30, 0xFD, 0x22, 0xEA, 0x01, 0x7B, 0x63, 0xCB, 0x6C, 0x8C, 0x3F, 0xC1, 0x4A, 0xDE, 0xA4, 0x87, 0xA1, 0xE2, 0xCF, 0x37, 0x25, 0xDB, 0x49, 0x04, 0xCE,
0xA8, 0x8D, 0x4D, 0x7C, 0x38, 0xB3, 0xBA, 0x88, 0x15, 0x3E, 0xEB, 0x43, 0xBB, 0x9D, 0x5F, 0xE6, 0x92, 0x02, 0xD0, 0x33, 0x6D, 0x44, 0x6A, 0x31, 0x42, 0x61, 0x79, 0xC4, 0xC2, 0xB1, 0x9B, 0x24,
0xE1, 0xC7, 0xC8, 0x75, 0xBE, 0x65, 0xAE, 0x40, 0x77, 0x16, 0x59, 0x83, 0x06, 0xC0, 0xEE, 0x20, 0x93, 0x91, 0x08, 0x03, 0x35, 0x8B, 0x5C, 0x68, 0x7D, 0x5E, 0x4F, 0xBC, 0x4E, 0x5B, 0x34, 0x1D,
0x1B, 0xEF, 0x58, 0x23, 0x67, 0x64, 0x0C, 0x2C, 0x9A, 0x6F, 0x2A, 0x41, 0x47, 0x4C, 0xFE, 0xB8, 0x3B, 0xEC, 0x28, 0x94, 0x73, 0x0B, 0x9F, 0xAD, 0x26, 0x86, 0x72, 0x5D, 0xD2, 0x1C, 0x1A, 0xED,
0xBF, 0xB7, 0x1E, 0x97, 0x9C, 0xB4, 0xA9, 0xE3, 0x48, 0x2B, 0xFF, 0xAB, 0x8F, 0xF4, 0x54, 0xC6, 0x51, 0x96, 0x62, 0x1F, 0xE5, 0xAA, 0x0A, 0xA2, 0x2E, 0x3A, 0x84, 0xFB, 0x81, 0xFC, 0xF3, 0x98,
0xB5, 0xBD, 0x90, 0xDA, 0xF7, 0x85, 0x0D, 0xD3, 0xC5, 0x07, 0xB6, 0x3C, 0x17, 0xA3, 0x3D, 0x8E, 0x53, 0x19, 0xA7, 0x11, 0xD6, 0xF8, 0x52, 0x6B, 0xCA, 0xCC, 0xD9, 0xE4, 0x13, 0x70, 0x5A, 0xA5,
]

EncTable=[0 for i in range(256)]

'''
#鬼哭街
hash0=0x1af59
hash1=0xacc1
'''


'''
#Axanael
hash0=0x18b61
hash1=0x27697
Thash=0x20101118
'''

#君と彼女と彼女の恋
hash0=0x1fd72
hash1=0x585d
Thash=0x12345678

def InitEncTable():
    for i in range(256):
        EncTable[DecTable[i]]=i

'''
struct entry{
0    name;
1    type;
2    dir_num;
3    data_off;
4    comprlen;
5    uncomprlen;
6    is_crypted;
7    is_compressed;
8    key;
9    dec_len;
10   hash0;
11   hash1;
}
'''
def EncryptEntry(entry,idx):
    thash=(entry[10]*entry[11])&0xffffffff
    for i in range(len(entry[0])):
        mi=(i*0xfc-(thash>>24)-(thash>>16)-(thash>>8)-thash-\
                      (idx>>24)-(idx>>16)-(idx>>8)-idx)&0xff
        t=(entry[0][i]-mi)&0xff
        entry[0][i]=t

def Encrypt(entry,bf):
    thash=Thash
    for ch in entry[0]:
        thash-=ch
    entry[8]=(thash*len(entry[0]))&0xffffffff
    key=((entry[10]*entry[11]+entry[8])*entry[5])&0xffffffff

    if entry[4]>4096+len(entry[0]):
        entry[9]=4096+len(entry[0])
    else:
        entry[9]=entry[4]

    for i in range(entry[9]):
        bf[i]=EncTable[(bf[i]+key+i)&0xff]

#君と彼女と彼女の恋
def Encrypt2(entry,bf):
    thash=Thash
    for ch in entry[0]:
        thash-=ch
    entry[8]=(thash*len(entry[0]))&0xffffffff
    key=((entry[10]*entry[11]+entry[8])*entry[5])&0xffffffff
    
    #int3()
    if entry[4]>4096+len(entry[0]):
        entry[9]=4096+len(entry[0])
    else:
        entry[9]=entry[4]

    for i in range(entry[9]):
        temp=EncTable[(~(bf[i]+key+i))&0xff]
        temp=EncTable[temp]
        bf[i]=EncTable[temp]

def packNpa(thedir,fname,is_compr,is_crypt):
    if not thedir.endswith('\\'):
        thedir+='\\'
    namepos=len(thedir)

    idxlen=0
    dircount=0
    filecount=0
    dirss=[]
    for root,dirs,files in os.walk(thedir):
        dirlen=len(root[namepos:].encode('932'))
        if dirlen>0:
            idxlen+=0x15+dirlen
            dirss.append(root[namepos:].encode('932'))
            dircount+=1
        else:
            dirlen=-1
            dirss.append('')
        for f in files:
            idxlen+=0x15+dirlen+1+len(f.encode('932'))
            filecount+=1

    fs=open(fname,'wb')
    idx=[]
    curpos=0
    curdir=0
    fs.seek(0x29+idxlen)
    for root,dirs,files in os.walk(thedir):
        dirlen=len(root[namepos:].encode('932'))
        if dirlen>0:
            rtdir=root[namepos:]+'\\'
            entry=[0 for i in range(12)]
            entry[0]=bytearray(root[namepos:].encode('932'))
            entry[1]=1
            if '\\' not in rtdir[0:-1]:
                entry[2]=0
            else:
                entry[2]=dirss.index(rtdir[0:-1].rsplit('\\',1)[0])
            entry[3]=curpos
            entry[10]=hash0
            entry[11]=hash1
            idx.append(entry)
            curdir+=1
        else:
            rtdir=u""
        for f in files:
            entry=[0 for i in range(12)]
            entry[0]=bytearray((rtdir+f).encode('932'))
            entry[1]=2
            entry[2]=curdir
            entry[3]=curpos
            infs=open(root+os.sep+f,'rb')
            entry[5]=os.path.getsize(root+os.sep+f)
            entry[6]=is_crypt
            entry[7]=is_compr
            entry[10]=hash0
            entry[11]=hash1
            if is_compr:
                stm=bytearray(zlib.compress(infs.read()))
            else:
                stm=bytearray(infs.read())
            infs.close()
            entry[4]=len(stm)
            if is_crypt:
                Encrypt2(entry,stm)
            fs.write(stm)
            curpos+=len(stm)
            idx.append(entry)

    for i in range(len(idx)):
        EncryptEntry(idx[i],i)

    idxbf=bytearray()
    for entry in idx:
        idxbf+=pack('I',len(entry[0]))
        idxbf+=entry[0]
        idxbf+=pack('<BIIII',entry[1],entry[2],entry[3],entry[4],entry[5])
    if len(idxbf)!=idxlen:
        int3()
    hdr=pack('<3sIIIBBIIIIII','NPA',1,hash0,hash1,is_compr,is_crypt,\
             filecount+dircount,dircount,filecount,0,0,idxlen)
    fs.seek(0)
    fs.write(hdr)
    fs.write(idxbf)
    fs.close()

InitEncTable()
packNpa(ur'D:\temp\nss',\
        ur'D:\temp\nss.npa',0,0)
##packNpa(ur'D:\Program Files\君と彼女と彼女の恋\nss1',\
##        ur'D:\Program Files\君と彼女と彼女の恋\nss-1.npa',1,1)
##packNpa(ur'K:\Program Files\アザナエル\cg',\
##        ur'K:\Program Files\アザナエル\cg-1.npa',0,1)
##packNpa(u'K:\\Program Files\\kikokugai\\nss2',\
##        u'K:\\Program Files\\kikokugai\\nss-1.npa',1,1)
